package x.ovo.wechat.bot.impl;

import lombok.RequiredArgsConstructor;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.thread.ThreadUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import x.ovo.wechat.bot.core.Constant;
import x.ovo.wechat.bot.core.Context;
import x.ovo.wechat.bot.core.WechatClient;
import x.ovo.wechat.bot.core.event.SystemEvent;
import x.ovo.wechat.bot.core.http.EngineConfig;
import x.ovo.wechat.bot.core.http.WechatApi;
import x.ovo.wechat.bot.core.util.WechatUtil;
import x.ovo.wechat.bot.impl.command.DefaultCommandManager;
import x.ovo.wechat.bot.impl.config.ClientConfig;
import x.ovo.wechat.bot.impl.contact.DefaultContactManager;
import x.ovo.wechat.bot.impl.core.HotReload;
import x.ovo.wechat.bot.impl.core.MessageConsumer;
import x.ovo.wechat.bot.impl.core.Monitor;
import x.ovo.wechat.bot.impl.core.SyncChecker;
import x.ovo.wechat.bot.impl.event.DefaultEventManager;
import x.ovo.wechat.bot.impl.http.DefaultCookieStore;
import x.ovo.wechat.bot.impl.http.DefaultHttpEngine;
import x.ovo.wechat.bot.impl.http.DefaultWechatApi;
import x.ovo.wechat.bot.impl.plugin.DefaultPluginManager;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.nio.charset.StandardCharsets;

/**
 * 微信客户端
 *
 * @author ovo on 2024/07/08.
 * @since 1.0.0
 */
@RequiredArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class DefaultWechatClient implements WechatClient {

    private final WechatApi api;
    private static final Logger log;
    private final Context context = Context.INSTANCE;
    private static final ClientConfig config = ClientConfig.get();

    static {
        // 设置线程名称
        Thread.currentThread().setName("wechat-bot");
        // 设置logback配置文件
        System.setProperty("logback.configurationFile", "./config/logback.xml");
        log = LoggerFactory.getLogger("WechatClient");

        if (config.getPrintBanner()) WechatUtil.printInfo();
        log.debug("bot client config: {}", config);
    }

    public static WechatClient create(WechatApi api) {
        return new DefaultWechatClient(api);
    }

    public static WechatClient create() {
        return create(new DefaultWechatApi());
    }

    @Override
    public void init() {
        // 注册关闭钩子
        Runtime.getRuntime().addShutdownHook(new Thread(this::stop));

        this.context.setApi(this.api);
        Context.INSTANCE.setOwner(config.getOwner());
        DefaultHttpEngine.INSTANCE.init(EngineConfig.defaultConfig());
        // 各管理器初始化并注册到上下文中
        DefaultEventManager.INSTANCE.init();
        DefaultCommandManager.INSTANCE.init();
        DefaultPluginManager.INSTANCE.init();
        DefaultContactManager.INSTANCE.init();

        // 创建必要文件夹
        this.mkdirs();
        this.saveDefaultConfig();
        log.info("客户端初始化完成");
    }

    @Override
    public void start() {
        try {
            this.context.setRunning(true);
            // 登录
            this.api.login(config.getAutoLogin());
            // 初始化微信
            this.api.init();
            // 刷新联系人信息
            this.context.getContactManager().flush();
            // 启动心跳同步线程
            ThreadUtil.newThread(new SyncChecker(), "sync-checker").start();
            // 启动消息消费线程
            ThreadUtil.newThread(new MessageConsumer(), "msg-consumer").start();
            // 启动心跳同步监听线程
            ThreadUtil.newThread(new Monitor(), "monitor").start();
            HotReload.create(this.context.getSession(), DefaultCookieStore.getStore()).save();
            log.info("wechat-bot 启动完成");
            new SystemEvent("[client] wechat-bot 启动完成").fire();
        } catch (Exception ex) {
            log.error("wechat-bot 启动失败: {}", ex.getMessage());
            log.debug("启动失败", ex);
            new SystemEvent("[client] wechat-bot 启动失败：" + ex.getMessage()).fire();
            System.exit(0);
        }
    }

    @Override
    public void stop() {
        // 如果登录成功，则保存登录信息
        if (this.context.isLogedin()) {
            HotReload.create(this.context.getSession(), DefaultCookieStore.getStore()).save();
        }
        this.context.setRunning(false);
        this.context.setLogedin(false);
        this.context.setAutoLogedin(false);
        this.context.getPluginManager().saveLimitConfig();
        this.context.getCommandManager().savePermissions();
        log.info("wechat-bot已停止，正在退出...\n\n");
        new SystemEvent("[client] wechat-bot 已停止").fire();
    }

    @Override
    public void mkdirs() {
        FileUtil.mkdir(Constant.Files.CONFIG_DIR);
        FileUtil.mkdir(Constant.Files.PLUGIN_DIR);
        FileUtil.mkdir(Constant.Files.LOG_DIR);
        if (config.getSaveMedia()) {
            FileUtil.mkdir(Constant.Files.IMAGE_DIR);
            FileUtil.mkdir(Constant.Files.VIDEO_DIR);
            FileUtil.mkdir(Constant.Files.VOICE_DIR);
        }
    }

    @Override
    public void saveDefaultConfig() {
        // 如果客户端配置文件不存在，则输出默认的客户端配置文件
        if (!Constant.Files.CONFIG_FILE.exists()) {
            BufferedReader reader = IoUtil.toUtf8Reader(this.getClass().getClassLoader().getResourceAsStream("client_config.yml"));
            BufferedWriter writer = FileUtil.getWriter(Constant.Files.CONFIG_FILE, StandardCharsets.UTF_8, false);
            IoUtil.copy(reader, writer);
        }
        // 如果日志配置文件不存在，则输出默认的日志配置文件
        if (!FileUtil.file(Constant.Files.CONFIG_DIR, "logback.xml").exists()) {
            BufferedReader reader = IoUtil.toUtf8Reader(this.getClass().getClassLoader().getResourceAsStream("logback.xml"));
            BufferedWriter writer = FileUtil.getWriter(FileUtil.file(Constant.Files.CONFIG_DIR, "logback.xml"), StandardCharsets.UTF_8, false);
            IoUtil.copy(reader, writer);
        }
    }
}
